/* 
 * File:   InputHandler.cpp
 * Copyright (C) 2008, 2009
 *		Sergio Padrino Recio (PadrinatoR)
 *		J. Daniel Expósito Polo (HellSpawn)
 *
 * Created on 8 de septiembre de 2008, 19:40
 *
 * This file is part of BombProject.
 * 
 * BombProject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
   
 * BombProject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with BombProject.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <SDL/SDL_events.h>

#include "InputHandler.h"
#include "Keyboard.h"
#include "Pad.h"

InputHandler* gInputHandler = InputHandler::getInstance();

InputHandler* InputHandler::mSingletonInstance = NULL;

/**
 * Returns a singleton instance.
 * @return Singleton instance.
 */
InputHandler* InputHandler::getInstance(){
	if(mSingletonInstance == NULL) mSingletonInstance = new InputHandler();
	
	return mSingletonInstance;
}

/**
 * Deletes the singleton instance if it was created.
 */
void InputHandler::deleteInstance(){
	if(mSingletonInstance != NULL) delete mSingletonInstance;
	
	mSingletonInstance = NULL;
}

/**
 * Constructor.
 */
InputHandler::InputHandler(){
	
}

/**
 * Destructor.
 */
InputHandler::~InputHandler(){
	
}

/**
 * Detects every input device that can be used in the application.
 */
void InputHandler::detectDevices(){
	mDevicesList.clear();
	SDL_JoystickEventState(SDL_ENABLE);
	//Keyboards
	//TODO: Aislar esto SOLO para PC
	Keyboard* keyb = new Keyboard(0);	
	keyb->init();
	
	mDevicesList.push_back(keyb);
	
	//Joysticks
	Uint16 num_joysticks = SDL_NumJoysticks();
	
	for(Uint16 i = 0; i < num_joysticks; i++){
		Pad* new_pad = new Pad(i);
		new_pad->init();
		
		mDevicesList.push_back(new_pad);
	}
}

/**
 * Returns a link to a button from a pressed button, and gives information about its device to the method caller.
 * @param button_info Device info to be returned.
 * @return Link to the pressed button.
 */
ButtonState* InputHandler::getLinkFromPressedButton(DeviceButtonInfo& button_info){
	ButtonState* button = NULL;
	SDL_Event event;
	
	for(;;){
		while(SDL_PollEvent(&event)){
			if(event.type == SDL_QUIT) exit(0);
		}
		
		for(int i = 0; i < mDevicesList.size(); i++){
			button = mDevicesList[i]->getLinkFromPressedButton(button_info);
			if(button != NULL)
				return button;
		}
	}
	
	return NULL;
}

/**
 * Returns a link to a button from a given device information.
 * @param button_info Device information.
 * @return Link to the specified button.
 */
ButtonState* InputHandler::getLinkFromButtonInfo(DeviceButtonInfo& button_info){
	for(int i = 0; i < mDevicesList.size(); i++){
		if(mDevicesList[i]->getDeviceIndex() == button_info.device_index && mDevicesList[i]->getDeviceType() == button_info.device_type){
			return mDevicesList[i]->getLinkFromButtonCode(button_info.button_code);
		}
	}
	
	return NULL;
}

/**
 * Updates every detected device.
 */
void InputHandler::update(){
	for(int i = 0; i < mDevicesList.size(); i++){
		mDevicesList[i]->update();
	}
}

/**
 * Destroys every detected device.
 */
void InputHandler::destroy(){
	for(int i = 0; i < mDevicesList.size(); i++){
		mDevicesList[i]->destroy();
		delete mDevicesList[i];
	}
	
	mDevicesList.clear();
}
